/*
 * @brief LPC Sensor Hub communication protocol definition
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2014
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#if !defined(__HOSTIF_PROTOCOL_H__)
#define   __HOSTIF_PROTOCOL_H__

#ifndef __KERNEL__
#include <stdint.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup SH_HOSTIF : Sensor hub host interface
 * @ingroup SENSOR_HUB
 * @{
 */
#ifdef __KERNEL__
#   define LPCSH_SUSPEND_DELAY 100			/* msec suspend delay*/
#endif

/** Maximum data payload to be transferred to host */
#ifndef PC_EMULATOR
	#ifndef UNIT_TEST
		#define HOSTIF_MAX_DATA_SIZE 252
	#else
		#define HOSTIF_MAX_DATA_SIZE 64
	#endif
#else
	#define HOSTIF_MAX_DATA_SIZE 128	// Temporary workaround for USB I2C bridge limit
#endif



/** Sensor IDs */
/** Must not exceed 0x7f, sincd MS bit is used to mark a stale sample */
enum LPCSH_SENSOR_ID {
	LPCSH_SENSOR_ID_FIRST = 0,

	LPCSH_SENSOR_ID_ACCELEROMETER = LPCSH_SENSOR_ID_FIRST,	// 00: !< calibrated accelerometer data
	LPCSH_SENSOR_ID_ACCELEROMETER_UNCALIBRATED,				// 01: !< uncalibrated accelerometer data
	LPCSH_SENSOR_ID_MAGNETIC_FIELD,							// 02: !< calibrated magnetometer data
	LPCSH_SENSOR_ID_MAGNETIC_FIELD_UNCALIBRATED,			// 03: !< uncalibrated magnetometer data
	LPCSH_SENSOR_ID_GYROSCOPE,								// 04: !< calibrated gyroscope data

	LPCSH_SENSOR_ID_GYROSCOPE_UNCALIBRATED,					// 05: !< uncalibrated gyroscope data
	LPCSH_SENSOR_ID_LIGHT,									// 06: !< light data
	LPCSH_SENSOR_ID_PRESSURE,								// 07: !< barometer pressure data
	LPCSH_SENSOR_ID_PROXIMITY,							    // 08: !< proximity data
	LPCSH_SENSOR_ID_RELATIVE_HUMIDITY,						// 09: !< relative humidity data

	LPCSH_SENSOR_ID_AMBIENT_TEMPERATURE,					// 10: !< ambient temperature data
	LPCSH_SENSOR_ID_GRAVITY,								// 11: !< gravity part of acceleration in body frame
	LPCSH_SENSOR_ID_LINEAR_ACCELERATION,					// 12: !< dynamic acceleration
	LPCSH_SENSOR_ID_ORIENTATION,							// 13: !< yaw, pitch, roll (also use this for Win8 Inclinometer)
	LPCSH_SENSOR_ID_ROTATION_VECTOR,						// 14: !< accel+mag+gyro quaternion

	LPCSH_SENSOR_ID_GEOMAGNETIC_ROTATION_VECTOR,			// 15: !< accel+mag quaternion
	LPCSH_SENSOR_ID_GAME_ROTATION_VECTOR,					// 16: !< accel+gyro quaternion
	LPCSH_SENSOR_ID_STEP_DETECTOR,							// 17: !< precise time a step occured
	LPCSH_SENSOR_ID_STEP_COUNTER,							// 18: !< count of sensitive steps
	LPCSH_SENSOR_ID_SIGNIFICANT_MOTION,						// 19:

	LPCSH_SENSOR_ID_ACTIVITY_CLASSIFICATION_STATE,          // 20: 
	LPCSH_SENSOR_ID_AUG_REALITY_COMPASS,					// 21: !< heading which switches to aug-reality mode when camera towards horizon (Win8 compass)
	LPCSH_SENSOR_ID_TAP_DETECTOR,							// 22: !< precise time a TAP occured
	LPCSH_SENSOR_ID_SHAKE_DETECTOR,							// 23: !< precise time a SHAKE occured
	LPCSH_SENSOR_ID_STEP_SEGMENT_DETECTOR,					// 24: !< identifys a possible step segment: first step, last step, mid step

	LPCSH_SENSOR_ID_VOICE_TRIGGER,							// 25: !< voice trigger event
    LPCSH_SENSOR_ID_IR_BLASTER_RX_PACKET,              		// 26: !< IR Blaster RX packet
    LPCSH_SENSOR_ID_IR_BLASTER_STATUS,                 		// 27: !< IR Blaster status
	LPCSH_SENSOR_ID_META_SENSOR_FLUSH_DONE,			        // 28: !< Meta Sensor ID mask, to indicate Sensor(s) Flush ended

	LPCSH_SENSOR_ID_COUNT,									// 29: !< max Sensor ID

	LPCSH_SENSOR_ID_FAKE_SENSOR  =   LPCSH_SENSOR_ID_COUNT,	// 29: !<  Meta Sensor ID, for FIFO padding when needed
};

#define ACCEL_DATA_NAME "Accelerometer"
#define UNCALIBRATED_ACCEL_DATA_NAME "Uncalibrated Accelerometer"
#define MAGNETIC_DATA_NAME "Magnetic Field"
#define UNCAL_MAGNETIC_DATA_NAME "Uncalibrated Magnetic Field"
#define ORIENTATION_DATA_NAME "Orientation"
#define GYROSCOPE_DATA_NAME "Gyroscope"
#define UNCAL_GYROSCOPE_DATA_NAME "Uncalibrated Gyroscope"
#define ROTATIONVECTOR_DATA_NAME "Rotation Vector"
#define GAME_ROTATIONVECTOR_DATA_NAME "Game Rotation Vector"
#define GEO_MAGNETIC_ROTATION_VECTOR_DATA_NAME "Geo Magnetic Rotation Vector"
#define LIGHT_DATA_NAME "Light"
#define PROXIMITY_DATA_NAME "Proximity"
#define PRESSURE_DATA_NAME "Pressure"
#define STEP_DETECTOR_NAME "Step Detector"
#define STEP_COUNTER_NAME "Step Counter"
#define LINEAR_ACCELERATION_DATA_NAME "Linear Acceleration"
#define GRAVITY_DATA_NAME "Gravity"
#define SIGNIFICANT_MOTION_DATA_NAME "Significant Motion Detector"
#define ACTIVITY_CLASSIFICATION_STATE_DATA_NAME "Activity Classification State Detector"
#define TEMPERATURE_DATA_NAME "Ambient Temperature"
#define RELATIVE_HUMIDITY_DATA_NAME "Relative Humidity"
#define TAP_DETECTOR_DATA_NAME "TAP Detector"
#define SHAKE_DETECTOR_DATA_NAME "SHAKE Detector"
#define VOICE_TRIGGER_DATA_NAME "voice trigger"

#define IR_BLASTER_LEARNING_DATA_NAME "ir blaster learning"
#define IR_BLASTER_STATUS_DATA_NAME "ir blaster status"

#define SENSOR_MANUFACTURER "NXP Semiconductors"

/*-------------------------------------------------------------------------------------------------*\
|    T Y P E   D E F I N I T I O N S
\*-------------------------------------------------------------------------------------------------*/

#define packed_struct  struct
#define packed_union  union
#pragma pack(push)
#pragma pack(1)

packed_struct lpcsh_motion_sensor_node {
	int16_t Data[3];	/*!< Raw sensor data */
};

packed_struct lpcsh_motion_uncal_sensor_node {
	int16_t Data[3];	/*!< Raw sensor data */
	int16_t Bias[3];	/*!< Raw sensor bias */
};

packed_struct lpcsh_proximity_sensor_node {
	int16_t Data;	/*!< Raw sensor data */
};

packed_struct lpcsh_light_sensor_node {
	int16_t Data;	/*!< Raw sensor data */
};

packed_struct lpcsh_temperature_sensor_node {
	int16_t Data;	/*!< Raw sensor data */
};

packed_struct lpcsh_pressure_sensor_node {
	int16_t Data;	/*!< Raw sensor data */
};

packed_struct lpcsh_humidity_sensor_node {
	int16_t Data;	/*!< Raw sensor data */
};

packed_struct lpcsh_significant_motion_node {
	unsigned char  significantMotionDetected;	/*!< bool */
};

packed_struct lpcsh_activity_classification_state_node {
	uint8_t Data;
};

packed_struct lpcsh_meta_sensor_flush_done_node {
	uint64_t flushSensorIdMask;
};

packed_struct lpcsh_orientation_node {
	int32_t Data[3];	/*!< Orientation vector data */
};

packed_struct lpcsh_quaternion_node {
	int16_t W;
	int16_t X;
	int16_t Y;
	int16_t Z;
	int16_t E_EST;
};

packed_struct lpcsh_sensor_node_header {
	uint8_t sensorId;	/*!< enum LPCSH_SENSOR_ID */
                        /*!< if MS bit is set, sample is stail */
	uint32_t timeStamp;	/*!< raw time stamp */
};

packed_struct lpcsh_step_sensor_node {
	uint32_t numTotalsteps;
};

packed_struct lpcsh_tap_sensor_node {
	uint8_t state;
};

packed_struct lpcsh_shake_sensor_node {
	uint8_t detected;
};

packed_struct lpcsh_voice_trigger_node {
	uint8_t index;
};

#define IR_BLASTER_RX_SUB_BLOCK_MAX_SIZE   64               /* max of 256 while size is uint8_t */

packed_struct lpcsh_ir_blaster_rx_node {
    uint8_t    size;                                       /* size of user data sub-block - max 256*/
	uint8_t    data[IR_BLASTER_RX_SUB_BLOCK_MAX_SIZE];		/* data array to be max Host xfer size */
};

//
// IR status reporting enums
//
enum IR_DRVR_STATUS{
     IR_DRVR_TX_DATA_REQUESTED,
     IR_DRVR_TX_DONE,
     IR_DRVR_RX_DATA_AVAILABLE,
     IR_DRVR_RX_LEARNING_SUCCESS,
     IR_DRVR_RX_LEARNING_FAILED,
};

packed_struct lpcsh_ir_blaster_status_node {
	uint8_t    status;		/* status code enum IR_DRVR_STATUS */
    uint16_t   param;
};

packed_struct lpcsh_sensor_node {
	struct lpcsh_sensor_node_header header;
	union {
		struct lpcsh_motion_sensor_node                   sensorData;
		struct lpcsh_motion_uncal_sensor_node             uncal_sensorData;
		struct lpcsh_quaternion_node                      quaternionData;
		struct lpcsh_orientation_node                     orientationData;
		struct lpcsh_step_sensor_node                     stepData;
		struct lpcsh_significant_motion_node              significantMotionData;
		struct lpcsh_light_sensor_node                    lightData;
		struct lpcsh_pressure_sensor_node                 pressureData;
		struct lpcsh_proximity_sensor_node                proximityData;
		struct lpcsh_humidity_sensor_node                 humidityData;
		struct lpcsh_temperature_sensor_node              temperature_sensor_node;
		struct lpcsh_activity_classification_state_node   activityClassificationStateData;
		struct lpcsh_tap_sensor_node                      tapDetectorData;
		struct lpcsh_shake_sensor_node                    shakeDetectorData;
		struct lpcsh_meta_sensor_flush_done_node          flushDone;
		struct lpcsh_voice_trigger_node                   voice_trigger;
		struct lpcsh_ir_blaster_rx_node                   ir_blaster_rx_node;
        struct lpcsh_ir_blaster_status_node               ir_blaster_status_node;
	} data;
};


packed_struct ShCmdGetHeader_get_8bits_param_t {
	uint8_t param;
};

packed_struct ShCmdGetHeader_get_16bits_param_t {
	uint16_t param;
};

#define LPCSH_MAX_CMD_LENGTH            16	/*!< Maximum command packet size */
#define LPCSH_MAX_SENSOR_ID             30

/** Host I/F command ID enums */
enum LPCSH_CMD_ID_T {
	LPCSH_CMD_WHO_AM_I = 0x00,			/*!< Provide 8 bits Device ID */
	LPCSH_CMD_GET_VERSION,				/*!< 2 byte response. Byte 0 major version, byte_! minor version */
	LPCSH_CMD_RESET,					/*!< Resets host interface */

	LPCSH_CMD_GET_DATA_LENGTH,	        /*!< Command used by I2C host interface only to get data length */
	LPCSH_CMD_GET_DATA,		            /*!< Command used by I2C host interface only to get sensor hub data. */

	LPCSH_CMD_SET_SUSPEND,				/*!< Command to indicate AP is suspended  */
	LPCSH_CMD_SET_RESUME,				/*!< Command to indicate AP is active     */

    LPCSH_CMD_GET_FIFO_SIZE,	        /*!< Command used by I2C host interface only to get the size of the largest FIFO */

	LPCSH_CMD_SENSOR_ENABLE = 0x20,		/*!< Command to enable virtual sensors. */
	LPCSH_CMD_GET_SENSOR_STATE,			/*!< Command to get virtual sensors state. */
	LPCSH_CMD_SET_DELAY,				/*!< Command to set sensor sample rate. */
	LPCSH_CMD_GET_DELAY,				/*!< Command to get sensor sample rate. */

	LPCSH_CMD_SET_BATCH,				/*!< Command to set sensor batch Latency. */
	LPCSH_CMD_SET_FLUSH,				/*!< Command to request flush of sensor data. */

#   if defined TRANSMIT_CAL_TO_SH

	LPCSH_CMD_SET_CALIBRATE,
	LPCSH_CMD_GET_CALIBRATE,
#   endif

	LPCSH_FORCE_APP_ENTRY = 0x30,		/*!< Forces app to start the secondary loader */

	LPCSH_VOICE_TRIGGER_WRITE = 0x40,	/*!< Command to write voice trigger user data */
	LPCSH_VOICE_TRIGGER_WRITE_LAST,		/*!< Command to write voice trigger user data last record */
	LPCSH_VOICE_TRIGGER_DISABLE,		/*!< Command to stop voice trigger process */
	LPCSH_VOICE_TRIGGER_ENABLE,		    /*!< Command to start voice trigger process */

	LPCSH_IR_BLASTER_START_TX = 0x50,	/*!< Command to transmit first IR blaster block */
	LPCSH_IR_BLASTER_NEXT_TX,			/*!< Command to transmit next IR blaster block */
	LPCSH_IR_BLASTER_LEARN_START,		/*!< Command to trigger IR blaster learning process */
	LPCSH_IR_BLASTER_RESET,				/*!< Command to abort any IR blaster operation */
};

/** Host I/F command structure. */
packed_struct LPCSH_CMD_t {
	uint8_t id;
	uint8_t params[LPCSH_MAX_CMD_LENGTH - 1];
};

packed_struct ShHubCmdHeader_t {
	uint8_t command;	/* enum LPCSH_HUB_COMMANDS */
};

packed_struct ShHubCmdHeader_8bits_param_t {
	uint8_t command;	/* enum LPCSH_HUB_COMMANDS */
	uint8_t param;
};

packed_struct ShSensorCmdHeader_t {
	uint8_t command;	/* enum LPCSH_SENSOR_ID_COMMANDS */
	uint8_t sensorId;	/* enum LPCSH_SENSOR_ID_ID */
};

packed_struct ShSensorSetCmdHeader_8bits_param_t {
	uint8_t command;	/* enum LPCSH_SENSOR_ID_COMMANDS */
	uint8_t sensorId;	/* enum LPCSH_SENSOR_ID_ID */
	uint8_t param;
};

packed_struct ShSensorSetCmdHeader_16bits_param_t {
	uint8_t command;	/* enum LPCSH_SENSOR_ID_COMMANDS */
	uint8_t sensorId;	/* enum LPCSH_SENSOR_ID_ID */
	uint16_t param;
};

packed_struct ShSensorSetCmdHeader_32bits_param_t {
	uint8_t command;	/* enum LPCSH_SENSOR_ID_COMMANDS */
	uint8_t sensorId;	/* enum LPCSH_SENSOR_ID_ID */
	uint32_t param;
};

packed_struct ShSensorSetCmdHeader_batch_t {
	uint8_t command;	/* enum LPCSH_SENSOR_ID_COMMANDS */
	uint8_t sensorId;	/* enum LPCSH_SENSOR_ID_ID */
	int flags;
	uint32_t period_us;
	uint32_t timeout_us;
};

packed_struct ShSensorSetCmdHeader_flush_t {
	uint8_t command;	/* enum LPCSH_SENSOR_ID_COMMANDS */
	uint8_t sensorId;	/* enum LPCSH_SENSOR_ID_ID */
};

packed_struct LPCSH_DataLen_t {
	uint16_t dataLen;
};

#define VOICE_TRIGGER_SUB_BLOCK_MAX_SIZE 128            /* size aligned to flash bank size on LPC5400x */


packed_struct ShVoiceTriggerWriteUserDataCommand_t {
	uint8_t command;									/* enum LPCSH_VOICE_TRIGGER_WRITE */
	uint32_t offset;									/* offset of user data sub-block*/
	uint16_t size;										/* size of user data sub-block*/
	uint8_t data[VOICE_TRIGGER_SUB_BLOCK_MAX_SIZE];		/* data of current sub-block */
};

packed_struct ShIrBlasterCommand_t {
	uint8_t command;									/* enum LPCSH_IR_BLASTER_TX   */
};

packed_struct lpcsh_ir_blaster_tx_data_header_t {
	uint8_t  command;									/* enum LPCSH_IR_BLASTER_TX   */
    uint16_t size;                                      /* size of user data sub-block - max 16k*/
};

#define IR_BLASTER_TX_SUB_BLOCK_MAX_SIZE   (HOSTIF_MAX_DATA_SIZE - sizeof(packed_struct lpcsh_ir_blaster_tx_data_header_t))

packed_struct lpcsh_ir_blaster_tx_command_t {
	struct     lpcsh_ir_blaster_tx_data_header_t	hdr;	/* IR message header   */
	uint8_t    data[IR_BLASTER_TX_SUB_BLOCK_MAX_SIZE];		/* data array to be max Host xfer size */
};

packed_union ShCmdHeaderUnion{
    struct ShSensorCmdHeader_t command;
    struct ShSensorSetCmdHeader_8bits_param_t       sensor_cmd_8bits_param;
    struct ShSensorSetCmdHeader_16bits_param_t      sensor_cmd_16bits_param;
    struct ShSensorSetCmdHeader_32bits_param_t      sensor_cmd_32bits_param;
    struct ShHubCmdHeader_t                         hubCmdHeader;
    struct ShHubCmdHeader_8bits_param_t             hub_cmd_8bits_param;
    struct ShSensorSetCmdHeader_batch_t             sensor_cmd_batch;
    struct ShVoiceTriggerWriteUserDataCommand_t     voice_trigger_write_user_data_sub_block;
    struct lpcsh_ir_blaster_tx_command_t  		    ir_blaster_tx_command;
};


/* defines data structure for HAL setting "batch" command via sysfs */
struct batchCommandParams {
	uint32_t flag;
	uint32_t samplerate_us;
	uint32_t timeoutenc_us;
};

packed_struct lpcsh_version_t {
	uint8_t major_version;        /* sensor hub firmware major version number */
	uint8_t minor_version;        /* sensor hub firmware minor version number */
};

packed_struct lpcsh_fifo_length_t {
    uint16_t fifo_size;           /* max size of sensor hub FIFO */	
};

#pragma pack(pop)

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif /* __HOSTIF_PROTOCOL_H__ */

